package light.im;

import java.util.HashMap;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import light.im.util.ByteConvertor;
import light.network.ByteData;
import light.network.IEndpointHandler;
import light.network.EndpointSession;
import light.network.Packet;
import light.network.object.PackObject;

/**
 * 数据分发器，请求分发
 * @author Ruby
 * 数据格式：
 * 	参数长度标记位 int -- 参数体 -- 数据位 []
 */
public class ActionDispather implements IEndpointHandler {

	public static final String RequestPackageKey = "reqId";
	
	private static final Logger logger = LoggerFactory.getLogger(ActionDispather.class);
	Map<String, IAction> actionStores = new HashMap<String, IAction>();
	
	//TODO 加入超时控制
	Map<Integer, IResponseHandler> responseDispatcher = new HashMap<Integer, IResponseHandler>();
	IMEndpoint imServer;
	
	public ActionDispather(IMEndpoint server)
	{
		imServer = server;
	}
	
	public ActionDispather registerAction(IAction action)
	{
		ActionName an = action.getClass().getAnnotation(ActionName.class);
		if(an!=null)
			actionStores.put(an.value(), action);
		else
			throw new RuntimeException("action name is not specified, action type: "+action.getClass().getName());
		return this;
	}
	public ActionDispather registerAction(String name, IAction action)
	{
		actionStores.put(name, action);
		return this;
	}
	
	ActionDispather self = this;
	
	@Override
	public void onAccept(EndpointSession ep) {
		
	}
	@Override
	public void onReceive(EndpointSession ep, Packet packet) {
		PackObject ob = null;
		try {
			ByteData data = packet.data();
			int hLength = ByteConvertor.getInt(data.array(), data.start());
			String header = new String(data.array(), data.start()+4, hLength);
			//System.err.println(header);
			ob = new PackObject(new JSONObject(header));
			int restLength = data.length()-4-hLength;
			if(restLength>0)
			{
				ob.setData(new ByteData(data.array(), data.start()+4+hLength, restLength));
			}
		} catch (JSONException e2) {
			logger.error(e2.toString());
			e2.printStackTrace();
			return;
		}
		
		//已注册请求响应，直接派发数据对象到 ResponseHandler
		int reqId = -1;
		if(ob.has(RequestPackageKey))
		{
			reqId = ob.getInt(RequestPackageKey);
			IResponseHandler han = responseDispatcher.get(reqId);
			if(han!=null)
			{
				han.onSuccess(ob);
				responseDispatcher.remove(reqId);
				return;
			}
		}
		
		if(ob.has("action"))
		{
			String actionName = ob.getString("action");
			IAction action = actionStores.get(actionName);
			if(action==null)
			{
				logger.error("Cannot find action \'"+actionName+"\'");
			}
			else
			{
				try {
					action.execute(reqId>-1?new UdpIMSession(ep, imServer).requestId(reqId):new UdpIMSession(ep, imServer), ob);
				} catch (Throwable e) {
					logger.error("Action execute error. "+e.toString());
					e.printStackTrace();
				}
			}
		}
		else
		{
			logger.error("No handler for this packet :"+ob);
		}
	}
	
	@Override
	public void onFail(EndpointSession ep, Throwable ext) {
		ext.printStackTrace();
	}

	/**
	 * 将数据包加入到响应列表中
	 * @param requestId
	 * @param handler
	 */
	public void registerResponse(Integer requestId, IResponseHandler handler)
	{
		responseDispatcher.put(requestId, handler);
	}
}
